﻿#include "multicurvewidget.h"
#include <random>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include "qcustomplot.h"
#include <QColor>
 

inline QColor getRandomColor() {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution<> dis(0, 255);

    int r = dis(gen);
    int g = dis(gen);
    int b = dis(gen);
    return QColor(r, g, b);
}

MultiCurveWidget::MultiCurveWidget(const QVector<double>& xData, const QVector<QVector<double>>& yData,
    const QVector<QString>& curveNames, QWidget* parent)
    : xData(xData), yData(yData), curveNames(curveNames), QWidget(parent) {
    initUI();
    updateCurves();
}

MultiCurveWidget::~MultiCurveWidget() {
    delete spbMCurveWidth;
    delete spbAveCurveWidth;
    delete spbFontSize;
    delete customPlot;
}

void MultiCurveWidget::on_spbMCurveWidth_valueChanged(int value) {
    for (int i = 0; i < yData.size(); ++i) {
        auto pen = customPlot->graph(i)->pen();
        pen.setWidth(value);
        customPlot->graph(i)->setPen(pen);
    }
    customPlot->replot();
}

void MultiCurveWidget::on_spbAveCurveWidth_valueChanged(int value) {
    int n = customPlot->graphCount();
    if (n > 0) {
        auto pen = customPlot->graph(n - 1)->pen();
        pen.setWidth(spbAveCurveWidth->value());
        pen.setStyle(Qt::DashLine);  // 设置为虚线
        customPlot->graph(n - 1)->setPen(pen);
    }
    customPlot->replot();
}

void MultiCurveWidget::on_spbFontSize_valueChanged(int value) 
{
    QFont font;
    font.setPointSize(spbFontSize->value());
    customPlot->xAxis->setLabelFont(font);
    customPlot->yAxis->setLabelFont(font);
    customPlot->xAxis->setTickLabelFont(font);
    customPlot->yAxis->setTickLabelFont(font);
    customPlot->legend->setFont(font);

    customPlot->rescaleAxes();
    customPlot->replot();
}

void MultiCurveWidget::initUI() {
    this->resize(820, 600);

    spbMCurveWidth = new QSpinBox();
    spbMCurveWidth->setRange(1, 20);
    spbMCurveWidth->setValue(1);


    spbAveCurveWidth = new QSpinBox();
    spbAveCurveWidth->setRange(1, 20);
    spbAveCurveWidth->setValue(5);

    spbFontSize = new QSpinBox();
    spbFontSize->setRange(1, 20);
    spbFontSize->setValue(12);

    QHBoxLayout* hbox = new QHBoxLayout();
    hbox->addWidget(new QLabel("Multi-Curve Width:"));
    hbox->addWidget(spbMCurveWidth);
    hbox->addWidget(new QLabel("Ave. Curve Width:"));
    hbox->addWidget(spbAveCurveWidth);
    hbox->addWidget(new QLabel("Font Size:"));
    hbox->addWidget(spbFontSize);
    
    chkShowLegend = new QCheckBox("Show Legend");
    chkShowLegend->setChecked(false);
    hbox->addWidget(chkShowLegend);

    btnUpdate = new QPushButton("Update");
    hbox->addWidget(btnUpdate);
    

    btnExportCurves = new QPushButton("Export Curves");
    hbox->addWidget(btnExportCurves);
    auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
    hbox->addItem(spacer);
    

    customPlot = new QCustomPlot();
    customPlot->resize(800, 600);
    customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom|QCP::iSelectLegend);
    

    // 设置图例位置为右侧
    customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignRight | Qt::AlignCenter);
    
    // 使图例可选择和可移动
    customPlot->legend->setSelectableParts(QCPLegend::spItems);
    customPlot->legend->setSelectedParts(QCPLegend::spItems);
    

    QFont font;
    font.setPointSize(spbFontSize->value());
    customPlot->legend->setFont(font);

    QVBoxLayout* mainLayout = new QVBoxLayout();
    mainLayout->addLayout(hbox);
    mainLayout->addWidget(customPlot);
    this->setLayout(mainLayout);

    connect(spbMCurveWidth, QOverload<int>::of(&QSpinBox::valueChanged), this, &MultiCurveWidget::on_spbMCurveWidth_valueChanged);
    connect(spbAveCurveWidth, QOverload<int>::of(&QSpinBox::valueChanged), this, &MultiCurveWidget::on_spbAveCurveWidth_valueChanged);
    connect(spbFontSize, QOverload<int>::of(&QSpinBox::valueChanged), this, &MultiCurveWidget::on_spbFontSize_valueChanged);
    connect(btnUpdate, &QPushButton::clicked, this, &MultiCurveWidget::on_btnUpdate_clicked);   
    connect(chkShowLegend, &QCheckBox::stateChanged, this, &MultiCurveWidget::on_chkShowLegend_stateChanged);
    connect(btnExportCurves, &QPushButton::clicked, this, &MultiCurveWidget::on_btnExportCurves_clicked);

}

void MultiCurveWidget::updateCurves() {
    QFont font;
    font.setPointSize(spbFontSize->value());

    customPlot->clearGraphs();
    customPlot->clearPlottables();
    customPlot->clearItems();
    customPlot->legend->clearItems();

    // 为每个数据集添加一条曲线
    for (int i = 0; i < yData.size(); ++i) {
        customPlot->addGraph();
        customPlot->graph(i)->setData(xData, yData[i]);
        customPlot->graph(i)->setPen(QPen(getRandomColor(), spbMCurveWidth->value()));  // 设置曲线颜色
        customPlot->graph(i)->setName(curveNames[i]);  // 设置曲线名称}
    }

    // 设置最后一条曲线为虚线
    int n = customPlot->graphCount();
    if (n > 0) {
        auto* lastCurve = customPlot->graph(n - 1);
        if (lastCurve) {
            QPen pen = lastCurve->pen();
            pen.setWidth(spbAveCurveWidth->value());
            pen.setStyle(Qt::DashLine);  // 设置为虚线
            lastCurve->setPen(pen);
        }
    }


    // 设置坐标轴名称
    customPlot->xAxis->setLabel("X");
    customPlot->yAxis->setLabel("Y");
    customPlot->xAxis->setLabelFont(font);
    customPlot->yAxis->setLabelFont(font);
    customPlot->xAxis->setTickLabelFont(font);
    customPlot->yAxis->setTickLabelFont(font);

    

    // 重新绘制
    customPlot->rescaleAxes();
    customPlot->replot();
}

void MultiCurveWidget::on_btnUpdate_clicked() {
    updateCurves();
}

void MultiCurveWidget::on_btnExportCurves_clicked() {
    // 导出曲线数据
    QString fileName = QFileDialog::getSaveFileName(this, "Export Curves", "", "CSV Files (*.csv)");
    if (fileName.isEmpty()) {
        return;
    }

    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "Export Curves", "Cannot write file " + fileName);
        return;
    }

    QTextStream out(&file);
    out << "X,";
    for (int i = 0; i < curveNames.size(); ++i) {
        out << curveNames[i] << ",";
    }
    out << "\n";

    for (int i = 0; i < xData.size(); ++i) {
        out << xData[i] << ",";
        for (int j = 0; j < yData.size(); ++j) {
            out << yData[j][i] << ",";
        }
        out << "\n";
    }

    file.close();
}

void MultiCurveWidget::on_chkShowLegend_stateChanged(int state)
{
    customPlot->legend->setVisible(state == Qt::Checked);
    customPlot->replot();
}

